package fi.solita.dojo.mazeserver.ui

import swing._
import swing.event._
import fi.solita.dojo.mazeserver.game._ 
import fi.solita.dojo.mazeserver.game.internal._ 
import fi.solita.dojo.mazeserver.map._ 

import java.awt.{ Color, Dimension, Graphics, Polygon }

class GameAreaComponent() extends Component{

	val cellHeight = 10
	val cellWidth = 10
	val marginLeft = 10
	val marginTop = 10
	val horizontalPadding = 1
	val verticalPadding = 1

	val horizontalMapAreaCells = 60
	val verticalMapAreaCells = 30 

	@volatile
	var map = MapGenerator.emptyMap()
	@volatile
	var players: PlayerList = new PlayerList(Nil)

	preferredSize = dimensions
	minimumSize = dimensions
	maximumSize = dimensions

	def dimensions(): Dimension = 
		new Dimension(horizontalMapAreaCells * (cellWidth + horizontalPadding) + 2 * marginLeft, 
				verticalMapAreaCells * (cellHeight + verticalPadding) + 2 * marginTop)

	override def paint(g:  Graphics) {
		for ((coords, loc) <- map.locations) {
			val (xx, yy) = gridCoordinates(coords.column, coords.row)
			drawArea(g, loc, xx, yy)
		}
		for (p <- players.players) {
			val (xx, yy) = gridCoordinates(p.coordinates.column, 
					p.coordinates.row)
					drawPlayerToken(g, xx, yy, p)
		}
	}

	private def gridCoordinates(x:  Int, y:  Int) = {
		(marginLeft + (cellWidth + horizontalPadding) * x, 
				marginTop + (cellHeight + verticalPadding) * y)
	}

	private def drawArea(g:  Graphics, loc:  GameLocation, x:  Int, y:  Int) {

		if (loc.passable) {
			if (loc.hole) {
				g.setColor(Color.GRAY)
				g.fillRect(x, y, cellWidth, cellHeight)
			} else {
				g.setColor(Color.WHITE)
				g.fillRect(x, y, cellWidth, cellHeight)			  
			}
			if (loc.point) {
				g.setColor(Color.RED)
				g.fillRect(x+3, y+3, cellWidth-6, cellHeight-6)
			}
		} else {
			g.setColor(Color.BLACK)
			g.fillRect(x, y, cellWidth, cellHeight)
		} 
	}

	def drawPlayerToken(g: Graphics, x: Int, y: Int, player: Player) {
		g.setColor(Color.BLACK)

		val p = new Polygon();

		player.heading match {    
		case Directions.North => {
			p.addPoint(x+(cellWidth/2),y);
			p.addPoint(x+cellWidth,y+cellWidth);
			p.addPoint(x,y+cellWidth); }
		case Directions.East => {
			p.addPoint(x+cellWidth,y+(cellWidth/2));
			p.addPoint(x,y+cellWidth);
			p.addPoint(x,y); }
		case Directions.South => {
			p.addPoint(x+(cellWidth/2),y+cellWidth);
			p.addPoint(x+cellWidth,y);
			p.addPoint(x,y); }
		case Directions.West => {
			p.addPoint(x,y+(cellWidth/2));
			p.addPoint(x+cellWidth,y+cellWidth);
			p.addPoint(x+cellWidth,y); }
		}
		g.drawPolygon(p)
		g.setColor(player.color._1)
		g.fillPolygon(p)
	}

	listenTo(GameWorld)
	listenTo(ServerUI)

	reactions += {
	case GameChangedEvent(map: GameMap, players: PlayerList) => {
		this.map = map;
		this.players = players
		repaint()
	}
	case PlayersUpdatedEvent(dto: PlayerList) => repaint()
	case RefreshEvent() => repaint()
	}
}